<?php

/**
 * Php Config writer.
 *
 * Helpful methods to make Config file.
 *
 * PHP versions 5
 * CAKEPHP versions 2.x
 * 
 * Green CMS - Content Management System and Framework Powerfull by Cakephp
 * Copyright 2012, GREEN GLOBAL CO., LTD (toancauxanh.vn)
 * 
 * CakePHP(tm) :  Rapid Development Framework (http://www.cakephp.org)
 * Copyright 2005-2011, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
 *
 * Licensed under The MIT License
 * Redistributions of files must retain the above copyright notice.
 *
 * @author        Technology Lab No.I <tech1@toancauxanh.vn>
 * @link          
 * @package       Green.Configure
 * @since         Green v 1.0
 * @license       MIT License (http://www.opensource.org/licenses/mit-license.php)
 */
class ConfigureInstance extends Configure {

    /**
     * Get instance of Config Reader
     *
     * @param string $key config of reader
     * @throws ConfigureException
     * return instance of Config Reader
     */
    public static function getReader($key) {
        if (!isset(Configure::$_readers[$key])) {
            throw new ConfigureException(__d('debug', 'Could not load Config Reader of key %s', $key));
        }
        return Configure::$_readers[$key];
    }

}

class PhpWriter {

    /**
     * Config named of PhpReader
     *
     * @var string
     */
    protected $_key = 'default';

    /**
     * Instance of PhpReader
     *
     * @var string
     */
    protected $_Reader;

    /**
     * Constructor for PHP Config file writing.
     *
     * @param string $path The path to read config files from.  Defaults to APP . 'Config' . DS
     * @throws ConfigureException
     */
    function __construct($key = null) {
        if (!$key) {
            $key = $this->_key;
        }
        $this->_Reader = ConfigureInstance::getReader($key);
        if (!method_exists($this->_Reader, 'getPath')) {
            throw new ConfigureException(__d('debug', 'Config reader objects must implement an getPath method.'));
        }
    }

    /**
     * Used to store a config file in application directory config
     *
     * Usage:
     * 
     * {{{
     *      $PhpWriter->write('App', array(
     *          'Datetime.timeZone' => 'Asia/Bangkok',
     *          'Datetime.firstDayOfWeek' => 1
     *      );
     * }}}
     * 
     * @param string $key includes type and key of config , it separated by a dot
     * @param array $data config to store
     * @return boolean true if save succeed,boolean false if save fail
     */
    public function write($key, $data, $order = false) {
        if (empty($data) || !is_array($data)) {
            return false;
        }
        $path = $this->_Reader->getPath($key);
        if ($order) {
            ksort($data);
        }
        if (file_put_contents($path, "<?php \n" . $this->_makeContent($data) . "?>")) {
            return true;
        }
        return false;
    }

    protected function _makeContent($data, $key = null) {
        $out = '';
        foreach ($data as $k => $v) {
            $tmpKey = $key . "[" . var_export($k, true) . "]";
            if (is_array($v)) {
                $out .= $this->_makeContent($v, $tmpKey);
            } else {
                $out.= "\$config$tmpKey=" . var_export($v, true) . ";\n";
            }
        }
        return $out;
    }

    /**
     * Used to delete a config file stored in application directory config
     *
     * Examples:
     * 
     * `$PhpWriter->delete('App')` will delete config file run on application startup
     * `$PhpWriter->delete('Module.System')` will delete config file run on System plugin startup
     * 
     * @param string $key includes type and key of config , it separated by a dot
     * @return boolean true if delete succeed,boolean false if deleted fail
     */
    public function delete($key) {
        $path = $this->_Reader->getPath($key);
        if (file_exists($path) && @unlink($path)) {
            return true;
        }
        return false;
    }

}
